<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="gd3ia" id="gd3ia"><span data-lake-id="ue9a30d8c" id="ue9a30d8c">典型回答</span></h1>
  <p data-lake-id="ub1b6262a" id="ub1b6262a"><br></p>
  <p data-lake-id="u62a57e23" id="u62a57e23"><br></p>
  <p data-lake-id="u05102caa" id="u05102caa"><span data-lake-id="u1fe825b9" id="u1fe825b9">看本文之前，请先了解一下binlog、redolog等，知道他们的作用及写入过程。</span></p>
  <p data-lake-id="u27d5c2d4" id="u27d5c2d4"><span data-lake-id="ue9d1be8a" id="ue9d1be8a">​</span><br></p>
  <p data-lake-id="u54af9307" id="u54af9307"><span data-lake-id="u73d54012" id="u73d54012">看到这里默认大家了解以上背景了，那么，正文开始：</span></p>
  <p data-lake-id="u110699ae" id="u110699ae"><span data-lake-id="u8bfdbf7d" id="u8bfdbf7d">​</span><br></p>
  <p data-lake-id="u43a20661" id="u43a20661"><span data-lake-id="ufd9bc1c3" id="ufd9bc1c3">MySQL的主从复制，是基于binlog实现的，主要过程是这样的：</span></p>
  <p data-lake-id="u23b3f29e" id="u23b3f29e"><img src="https://cdn.nlark.com/yuque/0/2024/png/5378072/1704281126630-1ca7a086-0f5d-487b-b944-7eda40180ed7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_38%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ubb89ad56" id="ubb89ad56"><span data-lake-id="u26160b81" id="u26160b81">​</span><br></p>
  <p data-lake-id="uec1367a1" id="uec1367a1"><span data-lake-id="ud02edde6" id="ud02edde6">1、从服务器在开启主从复制后，会创建出两个线程：I/O线程和SQL线程</span></p>
  <p data-lake-id="u7d322d4c" id="u7d322d4c"><span data-lake-id="u9bf8a0b4" id="u9bf8a0b4">​</span><br></p>
  <p data-lake-id="ubf9cb6c7" id="ubf9cb6c7"><span data-lake-id="u4ec29cf6" id="u4ec29cf6">2、从服务器的I/O线程，会尝试和主服务器建立连接，相对应的，主服务中也有一个binlog dump线程， 是专门来和从服务器的I/O线程做交互的。</span></p>
  <p data-lake-id="uc5bf848a" id="uc5bf848a"><span data-lake-id="u74f7bcb1" id="u74f7bcb1">​</span><br></p>
  <p data-lake-id="u7725ab27" id="u7725ab27"><span data-lake-id="uefcdf3bd" id="uefcdf3bd">3、从服务器的I/O线程会告诉主服务的dump线程自己要从什么位置开始接收binlog</span></p>
  <p data-lake-id="ubc166c20" id="ubc166c20"><span data-lake-id="u5172dabd" id="u5172dabd">​</span><br></p>
  <p data-lake-id="u5a67a030" id="u5a67a030"><span data-lake-id="uf02563f8" id="uf02563f8">4、主服务器在更新过程中，将更改记录保存到自己的binlog中，根据不同的binlog格式，记录的内容可能不一样。</span></p>
  <p data-lake-id="u4a51e727" id="u4a51e727"><span data-lake-id="uf31d701a" id="uf31d701a">​</span><br></p>
  <p data-lake-id="uae9577c6" id="uae9577c6"><span data-lake-id="u680015c7" id="u680015c7">5、在dump线程检测到binlog变化时，会从指定位置开始读取内容，然后会被slave的I/O线程把他拉取过去。</span></p>
  <ul list="u3733442c">
   <li fid="u7c4f6413" data-lake-id="u11e62fdb" id="u11e62fdb"><u><span data-lake-id="u36d8560c" id="u36d8560c">这里需要注意，有些资料上面说这里是主服务器向从服务器推的，但是，</span></u><u><strong><span data-lake-id="u0f514eb3" id="u0f514eb3">实际上是从服务器向主服务器拉的。</span></strong></u><u><span data-lake-id="u188ce1f6" id="u188ce1f6">（</span></u><a href="https://dev.mysql.com/doc/refman/8.0/en/replication-implementation.html" target="_blank" data-lake-id="u4f19f354" id="u4f19f354"><u><span data-lake-id="ub1aebce9" id="ub1aebce9">https://dev.mysql.com/doc/refman/8.0/en/replication-implementation.html</span></u></a><u><span data-lake-id="ue169bb63" id="ue169bb63"> ）</span></u></li>
  </ul>
  <p data-lake-id="u5733a600" id="u5733a600"><u><span data-lake-id="uebeed566" id="uebeed566">​</span></u><br></p>
  <blockquote data-lake-id="udadedb17" id="udadedb17">
   <p data-lake-id="uc9c36b0c" id="uc9c36b0c"><span data-lake-id="ud9056696" id="ud9056696">拉的模式，从库可以自行管理同步进度和处理延迟。</span></p>
  </blockquote>
  <p data-lake-id="udc7f278c" id="udc7f278c"><span data-lake-id="uc83b7d71" id="uc83b7d71">​</span><br></p>
  <p data-lake-id="uc522068d" id="uc522068d"><span data-lake-id="ubd3939bf" id="ubd3939bf">6、从服务器的I/O线程接收到通知事件后，会把内容保存在relay log中。</span></p>
  <p data-lake-id="ue7a8cc6c" id="ue7a8cc6c"><span data-lake-id="u1f399d3e" id="u1f399d3e">​</span><br></p>
  <p data-lake-id="uf346fa9c" id="uf346fa9c"><span data-lake-id="u533777ff" id="u533777ff">3、从服务器还有一个SQL线程，他会不断地读取他自己的relay log中的内容，把他解析成具体的操作，然后写入到自己的数据表中。</span></p>
  <p data-lake-id="u2a6e6334" id="u2a6e6334"><span data-lake-id="u646f05fb" id="u646f05fb">​</span><br></p>
  <h1 data-lake-id="SvFn2" id="SvFn2"><span data-lake-id="u46602f9a" id="u46602f9a">扩展知识</span></h1>
  <p data-lake-id="ua00dcdc0" id="ua00dcdc0"><br></p>
  <h2 data-lake-id="UAicG" id="UAicG"><span data-lake-id="u9cfc0770" id="u9cfc0770">复制方式</span></h2>
  <p data-lake-id="u630b562c" id="u630b562c"><br></p>
  <p data-lake-id="u4dbe4c8b" id="u4dbe4c8b"><span data-lake-id="u3b0e763d" id="u3b0e763d">MySQL目前支持多种复制方式，其中包括了全同步复制、异步复制和半同步复制。</span></p>
  <p data-lake-id="u6b661fa6" id="u6b661fa6"><span data-lake-id="uc5d1ecf6" id="uc5d1ecf6">​</span><br></p>
  <p data-lake-id="ub7b5e859" id="ub7b5e859"><strong><span data-lake-id="ub0d49a54" id="ub0d49a54">异步复制</span></strong><span data-lake-id="u3066e849" id="u3066e849">：这是MySQL默认的复制方式，在异步复制的方式中主库在执行完事务操作以后，会立刻给客户端返回。他不需要关心从库是否完成该事务的执行。</span></p>
  <p data-lake-id="ub86e19bd" id="ub86e19bd"><span data-lake-id="ub80d6236" id="ub80d6236">​</span><br></p>
  <p data-lake-id="u467b5e16" id="u467b5e16"><span data-lake-id="ucf4246ae" id="ucf4246ae">这种方式会导致一个问题，那就是当主库出现故障时，主库虽然事务执行完了，但是可能还没来得及把数据同步给从库，就挂了。那么当从库升级为主库之后，他会丢失了这次事务的变更内容。</span></p>
  <p data-lake-id="u27289db7" id="u27289db7"><span data-lake-id="ubec95aef" id="ubec95aef">​</span><br></p>
  <p data-lake-id="uec46d080" id="uec46d080"><strong><span data-lake-id="ub8d738d2" id="ub8d738d2">全同步复制</span></strong><span data-lake-id="u723f5fee" id="u723f5fee">：全同步复制的这个方式中，当主库执行完一个事务之后，他会等待所有的从库完成数据复制之后，才会给客户端反馈。</span></p>
  <p data-lake-id="u04077017" id="u04077017"><span data-lake-id="u9537279a" id="u9537279a">​</span><br></p>
  <p data-lake-id="u17be46a9" id="u17be46a9"><span data-lake-id="u9d13b9f3" id="u9d13b9f3">这种方式安全性可以保障了，但是性能很差。如果从库比较多的话，会导致整个过程更加长。</span></p>
  <p data-lake-id="ub989df34" id="ub989df34"><span data-lake-id="u6582be3c" id="u6582be3c">​</span><br></p>
  <p data-lake-id="u3dca47a1" id="u3dca47a1"><strong><span data-lake-id="udca2144b" id="udca2144b">半同步复制</span></strong><span data-lake-id="u16d9f239" id="u16d9f239">：半同步复制是介于全同步复制和异步复制之间的一种方案。他再执行完一个事务之后，也不会立刻给客户端反馈，但是也不会等所有从库都完成事务，而是等其中一个从库完成接收到事件之后，再反馈给客户端。</span></p>
  <p data-lake-id="ubdb47b96" id="ubdb47b96"><br></p>
  <p data-lake-id="u27467b57" id="u27467b57"><span data-lake-id="u839ff9cb" id="u839ff9cb">在半同步复制这个方案中，会在事务提交的2阶段都完成之后，等待从库接收到binlog，然后再返回成功。</span></p>
  <p data-lake-id="u825c4a15" id="u825c4a15"><span data-lake-id="ua314050a" id="ua314050a">​</span><br></p>
  <p data-lake-id="u40ea8482" id="u40ea8482"><span data-lake-id="uc7a9413c" id="uc7a9413c">​</span><br></p>
  <p data-lake-id="u9cc92cac" id="u9cc92cac"><span data-lake-id="uebd37b4d" id="uebd37b4d">在上面这篇中我们画过的一张图，如果把半同步复制的过程也加进去，那么就会变成：</span></p>
  <p data-lake-id="u4dfc4eac" id="u4dfc4eac"><span data-lake-id="u6873ead0" id="u6873ead0">​</span><br></p>
  <p data-lake-id="u665daf90" id="u665daf90"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1692363516478-340255ed-f1cb-4cfb-aae1-cf21970d78c3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_43%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="uabeaa98d" id="uabeaa98d"><br></p>
  <p data-lake-id="u0b0094a8" id="u0b0094a8"><br></p>
  <h2 data-lake-id="NAVTL" id="NAVTL"><span data-lake-id="ucbb2bff3" id="ucbb2bff3">主从延迟</span></h2>
  <p data-lake-id="u4cc5c436" id="u4cc5c436"><br></p>
  <h2 data-lake-id="yAbUn" id="yAbUn"><span data-lake-id="u79b92263" id="u79b92263">并行复制</span></h2>
  <p data-lake-id="u5407d5d6" id="u5407d5d6"><br></p>
  <p data-lake-id="ub0749071" id="ub0749071"><br></p>
  <p data-lake-id="u99497183" id="u99497183"><br></p>
  <p data-lake-id="ub3c0a4d3" id="ub3c0a4d3"><br></p>
  <p data-lake-id="u563ba037" id="u563ba037"><br></p>
  <p data-lake-id="u1abf9953" id="u1abf9953"><br></p>
  <p data-lake-id="u79f09679" id="u79f09679"><span data-lake-id="u7655662d" id="u7655662d">​</span><br></p>
 </body>
</html>